{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# K-Nearest Neighbors (KNN)\n",
    "\n",
    "K-Nearest Neighbors (KNN) is a classification algorithm that assigns a class label to a data point based on the class labels of its k nearest neighbors in the training set. It is a non-parametric algorithm, which means that it does not make any assumptions about the distribution of the data.\n",
    "\n",
    "The KNN algorithm works as follows:\n",
    "\n",
    "- Choose a value of k (the number of nearest neighbors to consider).\n",
    "- For each data point in the test set, compute its distance to all data points in the training set.\n",
    "- Select the k nearest neighbors based on their distances.\n",
    "- Assign the class label that appears most frequently among the k nearest neighbors to the test point.\n",
    "\n",
    "The distance between two data points can be computed using a distance metric such as Euclidean distance, Manhattan distance, or Minkowski distance. The choice of distance metric depends on the nature of the data and the problem at hand.\n",
    "\n",
    "One important aspect of the KNN algorithm is the choice of the value of k. A small value of k will result in a more flexible decision boundary that can capture complex patterns in the data, but may also lead to overfitting. A large value of k will result in a smoother decision boundary that may not capture fine details in the data, but is less prone to overfitting. The value of k is typically chosen using cross-validation.\n",
    "\n",
    "KNN can also be used for regression tasks, where the goal is to predict a continuous value instead of a class label. In this case, the predicted value for a test point is the average of the values of its k nearest neighbors in the training set."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Code \n",
    "Here is an implementation of the KNN classifier in Python:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import Counter\n",
    "import numpy as np\n",
    "\n",
    "class KNN:\n",
    "    def __init__(self, k=3, distance='euclidean'):\n",
    "        self.k = k\n",
    "        self.distance = distance\n",
    "        \n",
    "    def fit(self, X_train, y_train):\n",
    "        self.X_train = X_train\n",
    "        self.y_train = y_train\n",
    "        \n",
    "    def predict(self, X_test):\n",
    "        y_pred = []\n",
    "        for x in X_test:\n",
    "            # Compute distances between the test point and all training points\n",
    "            if self.distance == 'euclidean':\n",
    "                distances = np.linalg.norm(self.X_train - x, axis=1)\n",
    "            elif self.distance == 'manhattan':\n",
    "                distances = np.sum(np.abs(self.X_train - x), axis=1)\n",
    "            else:\n",
    "                distances = np.power(np.sum(np.power(np.abs(self.X_train - x), self.distance), axis=1), 1/self.distance)\n",
    "                \n",
    "            # Select the k nearest neighbors\n",
    "            nearest_indices = np.argsort(distances)[:self.k]\n",
    "            nearest_labels = self.y_train[nearest_indices]\n",
    "            \n",
    "            # Assign the class label that appears most frequently among the k nearest neighbors\n",
    "            label = Counter(nearest_labels).most_common(1)[0][0]\n",
    "            y_pred.append(label)\n",
    "        \n",
    "        return np.array(y_pred)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The KNN class has two main methods: fit and predict. The fit method takes the training data as input and stores it in instance variables. The predict method takes the test data as input and computes the class labels for each test point using the KNN algorithm.\n",
    "\n",
    "The predict method computes the distances between the test point and all training points, selects the k nearest neighbors based on the distances, and assigns the class label that appears most frequently among the k nearest neighbors to the test point.\n",
    "\n",
    "The distance parameter allows the user to choose the distance metric to use for computing distances. The default value is euclidean, but the user can also choose manhattan or any other value p for the Minkowski distance."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Test "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy: 1.0\n"
     ]
    }
   ],
   "source": [
    "from sklearn.datasets import load_iris\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "# Load the iris dataset\n",
    "iris = load_iris()\n",
    "\n",
    "# Split the data into training and test sets\n",
    "X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2, random_state=42)\n",
    "\n",
    "# Create a KNN classifier with k=5 and euclidean distance\n",
    "knn = KNN(k=5, distance='euclidean')\n",
    "\n",
    "# Train the classifier on the training data\n",
    "knn.fit(X_train, y_train)\n",
    "\n",
    "# Make predictions on the test data\n",
    "y_pred = knn.predict(X_test)\n",
    "\n",
    "# Compute the accuracy of the classifier\n",
    "accuracy = accuracy_score(y_test, y_pred)\n",
    "print(f\"Accuracy: {accuracy}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Visualization "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "from sklearn.datasets import load_iris\n",
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "# Load the iris dataset\n",
    "iris = load_iris()\n",
    "\n",
    "# Split the data into training and test sets\n",
    "X_train, X_test, y_train, y_test = train_test_split(iris.data[:, :2], iris.target, test_size=0.2, random_state=42)\n",
    "\n",
    "# Create a KNN classifier with k=5 and euclidean distance\n",
    "knn = KNN(k=5, distance='euclidean')\n",
    "\n",
    "# Train the classifier on the training data\n",
    "knn.fit(X_train, y_train)\n",
    "\n",
    "# Make predictions on the test data\n",
    "y_pred = knn.predict(X_test)\n",
    "\n",
    "# Create scatter plots of the test data with colored points representing the true and predicted labels\n",
    "fig, ax = plt.subplots()\n",
    "scatter1 = ax.scatter(X_test[y_test==0, 0], X_test[y_test==0, 1], c='b', cmap='viridis', label=iris.target_names[0])\n",
    "scatter2 = ax.scatter(X_test[y_test==1, 0], X_test[y_test==1, 1], c='g', cmap='viridis', label=iris.target_names[1])\n",
    "scatter3 = ax.scatter(X_test[y_test==2, 0], X_test[y_test==2, 1], c='r', cmap='viridis', label=iris.target_names[2])\n",
    "scatter4 = ax.scatter(X_test[:, 0], X_test[:, 1], c='k', cmap='viridis', marker='x', label='Predicted Label')\n",
    "ax.set_xlabel('Feature 1')\n",
    "ax.set_ylabel('Feature 2')\n",
    "ax.set_title('KNN Classifier Results')\n",
    "handles = [scatter1, scatter2, scatter3, scatter4]\n",
    "labels = [h.get_label() for h in handles]\n",
    "ax.legend(handles=handles, labels=labels)\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
